package datamining.algorithms.aprioriall;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * Main AprioriAll algorithm processing class
 *
 * @author Kelvin
 */
public class AprioriAll {
        private static<ItemType> int countSup(List<ApriorAllModelData<ItemType> > data, Sequence<ItemType> seq) {
                int count = 0;

                for (ApriorAllModelData<ItemType> m : data) {
                        Iterator<ItemSet<ItemType>> itemSetIter = seq.getItemSets().iterator();
                        Item<ItemType> targetItem = itemSetIter.next().getItems().iterator().next();

                        label: for (ItemSet<ItemType> itemSet : m.getSequence().getItemSets()) {
                                for (Item<ItemType> item : itemSet.getItems()) {
                                        if (item.equals(targetItem)) {
                                                if (itemSetIter.hasNext()) {
                                                        targetItem = itemSetIter.next().getItems()
                                                                        .iterator().next();
                                                        break;
                                                } else {
                                                        count++;
                                                        break label;
                                                }
                                        } else if (item.compareTo(targetItem) > 0) {
                                                break;
                                        }
                                }
                        }
                }

                return count;
        }

        public static <ItemType> Set<Sequence<ItemType>> generateC1(List<ApriorAllModelData<ItemType>> data) {

                Set<Sequence<ItemType>> ret = new TreeSet<Sequence<ItemType>>();

                for (ApriorAllModelData<ItemType> md : data) {
                        Sequence<ItemType> seq = md.getSequence();
                        for (ItemSet<ItemType> itemset : seq.getItemSets()) {
                                for (Item<ItemType> item : itemset.getItems()) {
                                        Sequence<ItemType> s = new Sequence<ItemType>();
                                        ItemSet<ItemType> is = new ItemSet<ItemType>();
                                        is.getItems().add(item);
                                        s.getItemSets().add(is);
                                        ret.add(s);
                                }
                        }
                }

                return ret;
        }

        public static <ItemType> Set<Sequence<ItemType>> generateCn(int n, Set<Sequence<ItemType>> lastFreqSeqs) {

                Set<Sequence<ItemType>> ret = new TreeSet<Sequence<ItemType>>();

                for (Sequence<ItemType> seq : lastFreqSeqs) {
                        for (Sequence<ItemType> seq2 : lastFreqSeqs) {
                                Iterator<ItemSet<ItemType>> seqIter = seq.getItemSets().iterator();
                                Iterator<ItemSet<ItemType>> seqIter2 = seq2.getItemSets().iterator();
                                for (int i = 0; i < n - 2; i++) {
                                        if (!seqIter.next().equals(seqIter2.next())) {
                                                continue;
                                        }
                                }
                                List<ItemSet<ItemType>> iss = new ArrayList<ItemSet<ItemType>>(seq.getItemSets());
                                iss.add(seqIter2.next());
                                ret.add(new Sequence<ItemType>(iss));
                        }
                }

                return ret;
        }

        public static <ItemType> Set<Sequence<ItemType>> generateLn(List<ApriorAllModelData<ItemType> > data,
                        Set<Sequence<ItemType>> candidates, double minSup) {

                Set<Sequence<ItemType>> ret = new TreeSet<Sequence<ItemType>>();
                double minSupCount = data.size() * minSup;

                for (Sequence<ItemType> seq : candidates) {
                        int fitCount = countSup(data, seq);

                        if (fitCount >= minSupCount) {
                                ret.add(seq);
                        }
                }

                return ret;
        }
}

